1
2
3
4
5
6
7 package gov.bnl.gums;
8
9 import java.util.StringTokenizer;
10 import java.util.regex.Matcher;
11 import java.util.regex.Pattern;
12
13 /*** Represent a VOMS extended proxy credential as defined in
14 * http://edg-wp2.web.cern.ch/edg-wp2/security/voms/edg-voms-credential.pdf.
15 * <p>
16 * A Fully Qualified Attribute Name consists of a VO, a group, a role and
17 * a capability. Only the VO is mandatory. The syntax is
18 * /VO[/group[/subgroup(s)]][/Role=role][/Capability=cap].
19 * <p>
20 * The class will always check that every modification matches the regex
21 * /[\w-\.]+(/[\w-\.]+)*(/Role=[\w-\.]+)?(/Capability=[\w-\.]+)?
22 * which fully defines all the characters allowed. This differs slightly from
23 * the one contained in the specification, as it cointained some small errors.
24 * It matches the description of the syntax of the document.
25 *
26 * @author Gabriele Carcassi
27 */
28 public class FQAN {
29
30 private String fqan;
31 private String vo;
32 private String group;
33 private String role;
34 private String capability;
35
36
37
38 private static Pattern fqanPattern = Pattern.compile("/[//w-//.]+(/[//w-//.]+)*(/Role=[//w-//.]+)?(/Capability=[//w-//.]+)?");
39
40 /***
41 * Creates a FQAN based on String representation. If the parsing fails, it will
42 * throw an exception.
43 * @param fqan A VOMS FQAN (i.e. "/atlas/production/Role=Leader")
44 */
45 public FQAN(String fqan) {
46 setFqan(fqan);
47 parseFqan(fqan);
48 generateFqan();
49 }
50
51 /*** Creates a FQAN based on the different pieces of information.
52 *
53 * @param vo The VO name, which cannot be null (i.e. "atlas")
54 * @param group A group path, including subgroups (i.e. "/production")
55 * @param role The role (i.e. "Leader")
56 * @param capability A capability (i.e. "capability"). Note capabilities are
57 * being deprecated in VOMS.
58 */
59 public FQAN(String vo, String group, String role, String capability) {
60 if (vo == null)
61 throw new IllegalArgumentException("The vo for a FQAN can't be null");
62 setVo(vo);
63 setGroup(group);
64 setRole(role);
65 setCapability(capability);
66 generateFqan();
67 }
68
69 /*** A full String representation of the FQAN.
70 *
71 * @return The Fully Qualified Attribute name String representation (i.e. "/atlas/production/Role=Leader")
72 */
73 public String getFqan() {
74 return this.fqan;
75 }
76
77 private void setFqan(String fqan) {
78 this.fqan = fqan;
79 }
80
81 /*** Returns the VO corresponding to the FQAN.
82 *
83 * @return The VO name (i.e. "atlas")
84 */
85 public String getVo() {
86 return this.vo;
87 }
88
89 private void setVo(String vo) {
90 if ((vo != null) && (!vo.matches("[//w-//.]+"))) {
91 throw new IllegalArgumentException("The vo '" + vo + "' is malformed");
92 }
93 this.vo = vo;
94 }
95
96 /*** The path which includes the groups and subgroups within the FQAN.
97 *
98 * @return The group path (i.e. "/production")
99 */
100 public String getGroup() {
101 return this.group;
102 }
103
104 private void setGroup(String group) {
105 if ((group != null) && (!group.matches("(/[//w-//.]+)+"))) {
106 throw new IllegalArgumentException("The group '" + group + "' is malformed");
107 }
108 this.group = group;
109 }
110
111 /*** The role used within the FQAN.
112 *
113 * @return The role or null if no role was specified
114 */
115 public String getRole() {
116 return this.role;
117 }
118
119 private void setRole(String role) {
120 if ((role != null) && (!role.matches("[//w-//.]+"))) {
121 throw new IllegalArgumentException("The role '" + role + "' is malformed");
122 }
123 this.role = role;
124 if ("NULL".equalsIgnoreCase(role)) {
125 this.role = null;
126 }
127 }
128
129 /***
130 * The capability used within the FQAN.
131 * @return The capability or null if none was specified.
132 */
133 public String getCapability() {
134 return this.capability;
135 }
136
137 private void setCapability(String capability) {
138 if ((capability != null) && (!capability.matches("[//w-//.]+"))) {
139 throw new IllegalArgumentException("The capability '" + capability + "' is malformed");
140 }
141 this.capability = capability;
142 if ("NULL".equalsIgnoreCase(capability)) {
143 this.capability = null;
144 }
145 }
146
147 private void parseFqan(String fqan) {
148
149 Matcher m = fqanPattern.matcher(fqan);
150 if (!m.matches())
151 throw new IllegalArgumentException("FQAN '" + fqan + "' is malformed (syntax: /VO[/group[/subgroup(s)]][/Role=role][/Capability=cap])");
152
153 StringTokenizer stk = new StringTokenizer(fqan, "/");
154 vo = stk.nextToken();
155 if (!stk.hasMoreTokens()) {
156 group = null;
157 role = null;
158 capability = null;
159 return;
160 }
161 String tempGroup = "";
162 String token = stk.nextToken();
163 while ((!token.startsWith("Role=") && !token.startsWith("Capability="))) {
164 tempGroup = tempGroup + "/" + token;
165 group = tempGroup;
166 if (!stk.hasMoreTokens()) {
167 role = null;
168 capability = null;
169 return;
170 }
171 token = stk.nextToken();
172 }
173 if (token.startsWith("Role=")) {
174 setRole(token.substring(5));
175 if (!stk.hasMoreTokens()) {
176 capability = null;
177 return;
178 }
179 token = stk.nextToken();
180 }
181 if (token.startsWith("Capability=")) {
182 setCapability(token.substring(11));
183 }
184 }
185
186 private void generateFqan() {
187 if (vo == null) {
188 fqan = null;
189 return;
190 }
191 StringBuffer bf = new StringBuffer();
192 bf.append('/');
193 bf.append(vo);
194 if (group != null)
195 bf.append(group);
196 if (role != null) {
197 bf.append("/Role=");
198 bf.append(role);
199 }
200 if (capability != null) {
201 bf.append("/Capability=");
202 bf.append(capability);
203 }
204 fqan = bf.toString();
205 }
206
207 /*** Returns the full string representation of the FQAN.
208 *
209 * @return The full FQAN (i.e. "/atlas/production/Role=Leader")
210 */
211 public String toString() {
212 return fqan;
213 }
214
215 /*** A hashcode generated from the string representation.
216 *
217 * @return A hashcode.
218 */
219 public int hashCode() {
220 if (fqan == null) return 0;
221 return fqan.hashCode();
222 }
223
224 /*** FQANs are equals to each other if their vo, group, role and capability
225 * are the same.
226 *
227 * @param obj Another object.
228 * @return True if the object was a FQAN with equal information. False otherwise.
229 */
230 public boolean equals(Object obj) {
231 if (obj == null) return false;
232 FQAN fqan2 = (FQAN) obj;
233 return (fqan2.fqan == null) ? fqan == null : fqan2.fqan.equals(fqan);
234 }
235
236 }